{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2.矩阵专栏\n",
    "\n",
    "吐槽一下：矩阵本身不难，但是矩阵的写作太蛋疼了 `(⊙﹏⊙)汗` 还好有`Numpy`，不然真的崩溃了...\n",
    "\n",
    "`LaTex`有没有一个集成了很多常用`公式`以及`推导`或者含`题库`的在线编辑器？\n",
    "\n",
    "代码裤子：<a href=\"https://github.com/lotapp/BaseCode\" target=\"_blank\">https://github.com/lotapp/BaseCode</a>\n",
    "\n",
    "在线编程系：<a href=\"https://mybinder.org/v2/gh/lotapp/BaseCode/master\" target=\"_blank\">https://mybinder.org/v2/gh/lotapp/BaseCode/master</a>\n",
    "\n",
    "数学基础：<a href=\"https://www.cnblogs.com/dotnetcrazy/p/9294292.html\" target=\"_blank\">https://www.cnblogs.com/dotnetcrazy/p/9294292.html</a>\n",
    "\n",
    "Numpy基础：<a href=\"https://www.cnblogs.com/dotnetcrazy/p/9309555.html\" target=\"_blank\">https://www.cnblogs.com/dotnetcrazy/p/9309555.html</a>\n",
    "\n",
    "## 2.1.矩阵的定义\n",
    "\n",
    "<a href=\"https://baike.baidu.com/item/矩阵\" target=\"_blank\">矩阵</a>：是一个按照长方阵列排列的复数或实数集合。\n",
    "\n",
    "通俗讲就是：**把数排成m行n列后，然后用中括号把它们括住，这种形式的组合就是矩阵了**～ eg：\n",
    "\n",
    "$\\begin{bmatrix}\n",
    "&a_{11}&a_{12}&a_{13}&...&a_{1n} \\\\\n",
    "&a_{21}&a_{22}&a_{23}&...&a_{2n} \\\\\n",
    "&a_{31}&a_{32}&a_{33}&...&a_{3n} \\\\\n",
    "&\\vdots&\\vdots&\\vdots&\\ddots&\\vdots\\\\\n",
    "&a_{m1}&a_{m2}&a_{m3}&...&a_{mn} \\\\\n",
    "\\end{bmatrix}$\n",
    "\n",
    "比如上面这个示例就是一个`m × n`的矩阵（m行n列的矩阵），如果`m=n`那么就叫做`n阶方阵`，eg:\n",
    "\n",
    "$\\begin{bmatrix}\n",
    "1&2&3 \\\\\n",
    "4&5&6 \\\\\n",
    "7&8&9\n",
    "\\end{bmatrix}$\n",
    "\n",
    "这个就是`3阶`方阵\n",
    "\n",
    "---\n",
    "\n",
    "如果回到中学，老师肯定都是通过**一次方程组**来引入矩阵（逆天的老师是这么讲的）：\n",
    "\n",
    "$\\begin{cases}x_1+x_2=-1\\\\2x_1-x_2=4\\\\3x_1+5x_2=-7\\\\\\end{cases}$ ==>  $\\begin{bmatrix}1&1\\\\2&-1\\\\3&5\\end{bmatrix}\\begin{bmatrix}x_1\\\\x_2\\end{bmatrix}=\\begin{bmatrix}-1\\\\4\\\\-7\\end{bmatrix}$\n",
    "\n",
    "如果你方程组都忘记怎么解的话...好吧还是说下吧：“比如这题，可以先把x2移到右边，这样x1就等于一个表达式了（x1=-x2-1），然后带入第二个表达式就可以解出x1和x2了，一次的其实两个表达式就可以解出了，剩下的你可以把值带进去验证一下”\n",
    "\n",
    "## 2.2.矩阵的运算（含幂运算）\n",
    "\n",
    "### 2.2.1.加、减\n",
    "\n",
    "加减比较简单，就是**对应元素相加减** (只有`行列都相同的矩阵`才可以进行)\n",
    "\n",
    "就不用麻烦的`LaTex`一行行打了，咱们用更方便的 **<a href=\"https://en.wikipedia.org/wiki/NumPy\" target=\"_blank\">NumPy</a>** 来演示一下矩阵加法（不懂代码的直接看结果，不影响阅读的)\n",
    "\n",
    "Numpy有专门的矩阵函数（np.mat），用法和`ndarray差不多`，我们这边使用经常使用`ndarray`类型，基础忘记了可以去查看一下：<a href=\"https://www.cnblogs.com/dotnetcrazy/p/9309555.html\" target=\"_blank\">Numpy基础</a>\n",
    "\n",
    "扩展：**矩阵的加法运算满足交换律：A + B = B + A** (乘法不行)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2 3]\n",
      " [4 5 6]\n",
      " [7 8 9]]\n",
      "-----\n",
      "[[0 1 2]\n",
      " [3 4 5]\n",
      " [6 7 8]]\n"
     ]
    }
   ],
   "source": [
    "# 创建两个集合\n",
    "A = np.arange(1,10).reshape((3,3))\n",
    "B = np.arange(9).reshape((3,3))\n",
    "\n",
    "print(A)\n",
    "print(\"-\"*5)\n",
    "print(B)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1,  3,  5],\n",
       "       [ 7,  9, 11],\n",
       "       [13, 15, 17]])"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 加法\n",
    "A + B"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1,  3,  5],\n",
       "       [ 7,  9, 11],\n",
       "       [13, 15, 17]])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 和A+B相等\n",
    "B + A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 1, 1],\n",
       "       [1, 1, 1],\n",
       "       [1, 1, 1]])"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 减法\n",
    "A - B"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "################ 变化来了 ################"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0 1 2]\n",
      " [3 4 5]]\n",
      "-----\n",
      "[[0 1]\n",
      " [2 3]\n",
      " [4 5]]\n"
     ]
    }
   ],
   "source": [
    "# 之前说过 ”只有行列都相同的矩阵才可以进行“ 来验证一下\n",
    "# 创建一个2行3列的矩阵\n",
    "C = np.arange(6).reshape((2,3))\n",
    "D = np.arange(6).reshape((3,2))\n",
    "\n",
    "print(C)\n",
    "print(\"-\"*5)\n",
    "print(D)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "operands could not be broadcast together with shapes (2,3) (3,2) ",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-8-bc97e29f7e31>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;31m# 2行3列的矩阵 + 3行2列的矩阵\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mC\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mD\u001b[0m \u001b[0;31m# 不同形状的矩阵不能进行加运算\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m: operands could not be broadcast together with shapes (2,3) (3,2) "
     ]
    }
   ],
   "source": [
    "# 2行3列的矩阵 + 3行2列的矩阵\n",
    "C + D # 不同形状的矩阵不能进行加运算"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "operands could not be broadcast together with shapes (2,3) (3,2) ",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-9-ca5169d0bf6c>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mC\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0mD\u001b[0m \u001b[0;31m# 不同形状的矩阵不能进行减运算\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m: operands could not be broadcast together with shapes (2,3) (3,2) "
     ]
    }
   ],
   "source": [
    "C - D # 不同形状的矩阵不能进行减运算"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.2.2.数乘、数除\n",
    "\n",
    "这个也比较简单，就是和**每个元素相乘**，eg:`2×A`，A原本的每一个元素都扩大了两倍\n",
    "\n",
    "数除其实就是乘以倒数（1/x）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2 3]\n",
      " [4 5 6]\n",
      " [7 8 9]]\n"
     ]
    }
   ],
   "source": [
    "print(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 2,  4,  6],\n",
       "       [ 8, 10, 12],\n",
       "       [14, 16, 18]])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 比如2×A，A原本的每一个元素都扩大了两倍\n",
    "2 * A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2 3]\n",
      " [4 5 6]\n",
      " [7 8 9]]\n"
     ]
    }
   ],
   "source": [
    "print(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.5, 1. , 1.5],\n",
       "       [2. , 2.5, 3. ],\n",
       "       [3.5, 4. , 4.5]])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 友情提醒：Numpy里面的运算基本上都是针对每一个元素\n",
    "A / 2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.2.3.矩阵乘法\n",
    "\n",
    "矩阵乘法还是要用`LaTex`演示一下的，不然有些朋友可能还是觉得比较抽象：（大家有什么好用的LaTex在线编辑器可以推荐的）\n",
    "\n",
    "拿上面那个方程组来演示一下：\n",
    "\n",
    "$\\begin{bmatrix}1&1\\\\2&-1\\\\3&5\\end{bmatrix}\\begin{bmatrix}x_1\\\\x_2\\end{bmatrix} ==> \\begin{cases}x_1+x_2\\\\2x_1-x_2\\\\3x_1+5x_2\\end{cases}$\n",
    "\n",
    "稍微变化一下就更形象了：\n",
    "\n",
    "$\\begin{bmatrix}1&1\\\\2&-1\\\\3&5\\end{bmatrix}\\begin{bmatrix}x_1&y_1\\\\x_2&y_2\\end{bmatrix} ==> \\begin{cases}x_1+x_2\\\\2x_1-x_2\\\\3x_1+5x_2\\end{cases} \\begin{cases}y_1+y_2\\\\2y_1-x_2\\\\3y_1+5y_2\\end{cases}==>\\begin{bmatrix}x_1+x_2&y_1+y_2\\\\2x_1-x_2&2y_1-y_2\\\\3x_1+5x_2&3y_1+5y_2\\end{bmatrix}$\n",
    "\n",
    "举个简单的例子：A×B\n",
    "\n",
    "$\\begin{bmatrix} 1&2 \\\\3&4 \\end{bmatrix}\\begin{bmatrix} 4&3 \\\\2&1 \\end{bmatrix}=\\begin{bmatrix} 1*4+2*2&1*3+2*1 \\\\3*4+4*2&3*3+4*1 \\end{bmatrix}=\\begin{bmatrix} 8&5 \\\\20&13 \\end{bmatrix}$\n",
    "\n",
    "以后记不得怎么乘就自己推一下，值得注意的是：\n",
    "\n",
    "**两个矩阵的乘法仅当第一个矩阵A的列数(column)和另一个矩阵B的行数(row)相等才可以进行计算**\n",
    "\n",
    "你这样想就记得了：$\\begin{bmatrix} 1&2 \\\\3&4 \\end{bmatrix}\\begin{bmatrix} x_1 \\end{bmatrix} 还原成方程组就是这样\\begin{cases}1*x_1+2*?\\\\3*x_1+4*?\\end{cases}\\\\这是什么鬼？至少得这样吧：\\begin{bmatrix} 1&2 \\\\3&4 \\end{bmatrix}\\begin{bmatrix} x_1 \\\\x_2 \\end{bmatrix}$\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2]\n",
      " [3 4]]\n",
      "-----\n",
      "[[4 3]\n",
      " [2 1]]\n"
     ]
    }
   ],
   "source": [
    "# 通过代码看一看\n",
    "A = np.array([[1,2],[3,4]])\n",
    "B = np.array([[4,3],[2,1]])\n",
    "\n",
    "print(A)\n",
    "print(\"-\"*5)\n",
    "print(B)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 8,  5],\n",
       "       [20, 13]])"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 注意一下，Numpy里面的乘法默认是每个数对应相乘\n",
    "# 如果是矩阵相乘可以使用dot()方法\n",
    "# 或者你创建矩阵对象，这样×默认就是矩阵乘法了\n",
    "\n",
    "A.dot(B) # 矩阵A×矩阵B"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "程序验证了我们上面的运算结果，还得注意一下：\n",
    "\n",
    "`A×B`和`B×A`是不一样的，eg：B×A\n",
    "\n",
    "$\\begin{bmatrix} 4&3 \\\\2&1 \\end{bmatrix}\\begin{bmatrix} 1&2 \\\\3&4 \\end{bmatrix}=\\begin{bmatrix} 4*1+3*3&4*2+3*4 \\\\2*1+1*3&2*2+1*4 \\end{bmatrix}=\\begin{bmatrix} 13&20 \\\\5&8 \\end{bmatrix}$\n",
    "\n",
    "如果你乘着乘着就忘记到底怎么乘，就把右边的矩阵换成x1,x2，然后就会了"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2]\n",
      " [3 4]]\n",
      "-----\n",
      "[[4 3]\n",
      " [2 1]]\n"
     ]
    }
   ],
   "source": [
    "print(A)\n",
    "print(\"-\"*5)\n",
    "print(B)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[13, 20],\n",
       "       [ 5,  8]])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B.dot(A) # 矩阵B×矩阵A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "################ 变化来了 ################"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2]\n",
      " [3 4]]\n",
      "-----\n",
      "[[0 1]\n",
      " [2 3]\n",
      " [4 5]]\n"
     ]
    }
   ],
   "source": [
    "# 来验证一下”两个矩阵的乘法仅当第一个矩阵A的列数(column)和另一个矩阵D的行数(row)相等才可以进行计算“\n",
    "print(A)\n",
    "print(\"-\"*5)\n",
    "print(D)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "shapes (2,2) and (3,2) not aligned: 2 (dim 1) != 3 (dim 0)",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-20-c1a9f22a6f8d>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;31m# A有2列 D有3行\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mA\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mD\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# 不能乘\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m: shapes (2,2) and (3,2) not aligned: 2 (dim 1) != 3 (dim 0)"
     ]
    }
   ],
   "source": [
    "# A有2列 D有3行\n",
    "A.dot(D) # 不能乘"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 3,  4],\n",
       "       [11, 16],\n",
       "       [19, 28]])"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 你反过来就符合A的列数=D的行数了\n",
    "D.dot(A)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.2.4.幂乘、幂运算\n",
    "\n",
    "幂乘比较简单，就是**每个元素开平方**，不一定是方阵\n",
    "\n",
    "必须是方阵才能进行<a href=\"https://baike.baidu.com/item/幂运算\" target=\"_blank\">幂运算</a>，比如`A²=A×A`（矩阵相乘前提：`第一个矩阵A的行=第二个矩阵A的列==>方阵`）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2]\n",
      " [3 4]]\n",
      "-----\n",
      "[[0 1 2]\n",
      " [3 4 5]]\n"
     ]
    }
   ],
   "source": [
    "print(A)\n",
    "print(\"-\"*5)\n",
    "print(C)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1,  4],\n",
       "       [ 9, 16]])"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 幂乘(每个元素开平方) \n",
    "np.power(A,2) # 使用 A**2也一样"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  1,  4],\n",
       "       [ 9, 16, 25]])"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 幂乘(不一定是方阵) \n",
    "np.power(C,2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "################ 方阵幂运算 ################"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 37,  54],\n",
       "       [ 81, 118]])"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# A*A*A\n",
    "np.linalg.matrix_power(A,3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "input must be a square array",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-27-73f04ef7b54c>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;31m# 不是方阵就over\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlinalg\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmatrix_power\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mC\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m~/anaconda3/lib/python3.6/site-packages/numpy/matrixlib/defmatrix.py\u001b[0m in \u001b[0;36mmatrix_power\u001b[0;34m(M, n)\u001b[0m\n\u001b[1;32m    137\u001b[0m     \u001b[0mM\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0masanyarray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mM\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    138\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0mM\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mndim\u001b[0m \u001b[0;34m!=\u001b[0m \u001b[0;36m2\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0mM\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m!=\u001b[0m \u001b[0mM\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 139\u001b[0;31m         \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"input must be a square array\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    140\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0missubdtype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mN\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minteger\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    141\u001b[0m         \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"exponent must be an integer\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mValueError\u001b[0m: input must be a square array"
     ]
    }
   ],
   "source": [
    "# 不是方阵就over\n",
    "np.linalg.matrix_power(C,3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**来个小结 + 扩展**：\n",
    "\n",
    "矩阵的加法运算满足交换律：`A + B = B + A`\n",
    "\n",
    "矩阵的乘法满足结合律和对矩阵加法的分配律：\n",
    "\n",
    "结合律：`(AB)C = A(BC)`\n",
    "\n",
    "左分配律：`(A + B)C = AC + BC`\n",
    "\n",
    "右分配律：`C(A + B) = CA + CB`\n",
    "\n",
    "矩阵的乘法与数乘运算之间也满足类似结合律的规律；与转置之间则满足倒置的\n",
    "\n",
    "分配律：`c(A + B) = cA + cB`\n",
    "\n",
    "结合律：`c(AB) = (cA)B = A(cB)`\n",
    "\n",
    "矩阵乘法**不满足交换律** 一般来说，矩阵A及B的乘积AB存在，但BA不一定存在，即使存在，大多数时候`AB ≠ BA`\n",
    "\n",
    "---\n",
    "\n",
    "## 2.3.特殊矩阵\n",
    "\n",
    "### 2.3.1.零矩阵\n",
    "\n",
    "零矩阵就是所有的元素都是0\n",
    "\n",
    "$\n",
    "\\begin{bmatrix}\n",
    "0&0&0 \\\\\n",
    "0&0&0 \\\\\n",
    "0&0&0\n",
    "\\end{bmatrix}\n",
    "$\n",
    "\n",
    "同样的：**全1矩阵**就是所有元素都是1\n",
    "\n",
    "$\n",
    "\\begin{bmatrix}\n",
    "1&1&1 \\\\\n",
    "1&1&1 \\\\\n",
    "1&1&1\n",
    "\\end{bmatrix}\n",
    "$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0., 0., 0., 0., 0.])"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 一维\n",
    "# 可以指定类型 np.zeros(5,dtype=int)\n",
    "np.zeros(5) # 完整写法：np.zeros((5,))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0., 0., 0., 0., 0.],\n",
       "       [0., 0., 0., 0., 0.]])"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 二维\n",
    "np.zeros((2,5))# 建议用元组，官方文档都是元组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[0., 0., 0., 0., 0.],\n",
       "        [0., 0., 0., 0., 0.]],\n",
       "\n",
       "       [[0., 0., 0., 0., 0.],\n",
       "        [0., 0., 0., 0., 0.]]])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 三维 ==> 可以这么理解，2个2*5（2行5列）的矩阵\n",
    "np.zeros((2,2,5))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "################ 全1矩阵 ################"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1., 1., 1., 1., 1.])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# `np.ones(tuple)` 用法和`np.zeros(tuple)`差不多\n",
    "# 可以指定类型 np.ones(5,dtype=int)\n",
    "# 一维\n",
    "np.ones(5) # 完整写法 np.ones((5,))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 1., 1., 1., 1.],\n",
       "       [1., 1., 1., 1., 1.]])"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 二维，传一个shape元组\n",
    "np.ones((2,5))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[1., 1., 1., 1., 1.],\n",
       "        [1., 1., 1., 1., 1.]],\n",
       "\n",
       "       [[1., 1., 1., 1., 1.],\n",
       "        [1., 1., 1., 1., 1.]]])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 三维 可以理解为两个二维数组\n",
    "np.ones((2,2,5))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "################ 指定值矩阵 ################"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[222, 222, 222, 222, 222],\n",
       "       [222, 222, 222, 222, 222],\n",
       "       [222, 222, 222, 222, 222]])"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 创建指定值的矩阵：\n",
    "np.full((3,5),222)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[222., 222., 222., 222., 222.],\n",
       "       [222., 222., 222., 222., 222.],\n",
       "       [222., 222., 222., 222., 222.]])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 创建指定值的矩阵，浮点类型\n",
    "np.full((3,5),222.0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.3.3.转置矩阵\n",
    "\n",
    "**<a href=\"https://baike.baidu.com/item/转置矩阵\" target=\"_blank\">转置矩阵</a>** ：将矩阵的行列互换得到的新矩阵(行列式不变)\n",
    "\n",
    "`m行×n列`的矩阵行和列交换后就变成了`n行×m列`的矩阵，eg：`3行×2列` ==> `2行×3列`\n",
    "\n",
    "$\\begin{bmatrix}1&2 \\\\3&4 \\\\5&6\\end{bmatrix}^T ==> \\begin{bmatrix}1&3&5 \\\\2&4&6\\end{bmatrix}$\n",
    "\n",
    "矩阵的转置满足分配律：\n",
    "\n",
    "$(A + B)^T = A^T + B^T$\n",
    "\n",
    "$(AB)^T = B^TA^T$\n",
    "\n",
    "再次提醒：**两个矩阵的乘法仅当第一个矩阵A的列数(column)和另一个矩阵B的行数(row)相等才可以进行计算**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0 1 2]\n",
      " [3 4 5]]\n"
     ]
    }
   ],
   "source": [
    "A = np.arange(6).reshape((2,3))\n",
    "\n",
    "print(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 3],\n",
       "       [1, 4],\n",
       "       [2, 5]])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 转置矩阵（行列互换）\n",
    "A.T"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[4 4 7]\n",
      " [5 3 9]]\n"
     ]
    }
   ],
   "source": [
    "B = np.random.randint(10,size=(2,3))\n",
    "\n",
    "print(B)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "################ 验证系列 ################"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 4  8]\n",
      " [ 5  7]\n",
      " [ 9 14]]\n",
      "-----\n",
      "[[ 4  8]\n",
      " [ 5  7]\n",
      " [ 9 14]]\n"
     ]
    }
   ],
   "source": [
    "# 验证一下(A+B)^T=A^T+B^T\n",
    "print(A.T + B.T)\n",
    "print(\"-\"*5)\n",
    "print((A+B).T)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ True,  True],\n",
       "       [ True,  True],\n",
       "       [ True,  True]])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 验证一下(A+B)^T=A^T+B^T\n",
    "# 其实也再一次验证了，Numpy运算符默认是对每一个元素的操作\n",
    "(A+B).T == A.T + B.T"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "################ 验证系列 ################"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0 1]\n",
      " [2 3]\n",
      " [4 5]]\n",
      "[[4 4 7]\n",
      " [5 3 9]]\n"
     ]
    }
   ],
   "source": [
    "# 把A变成3*2的矩阵，不够元素用0补\n",
    "# reshape：有返回值，不对原始多维数组进行修改\n",
    "# resize：无返回值，会对原始多维数组进行修改\n",
    "A.resize(3,2)\n",
    "\n",
    "print(A)\n",
    "print(B)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 5 23 41]\n",
      " [ 3 17 31]\n",
      " [ 9 41 73]]\n",
      "-----\n",
      "[[ 5 23 41]\n",
      " [ 3 17 31]\n",
      " [ 9 41 73]]\n"
     ]
    }
   ],
   "source": [
    "# 验证(AB)^T=B^T×A^T\n",
    "print((A.dot(B)).T)\n",
    "print(\"-\"*5)\n",
    "print((B.T).dot(A.T))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.3.3.上三角矩阵和下三角矩阵\n",
    "\n",
    "**<a href=\"https://baike.baidu.com/item/上三角矩阵\" target=\"_blank\">上三角矩阵</a>** ：主对角线以下都是零的**方阵**\n",
    "\n",
    "$\\begin{bmatrix}\n",
    "2&9&4&7 \\\\\n",
    "0&7&3&3 \\\\\n",
    "0&0&6&1 \\\\\n",
    "0&0&0&1\n",
    "\\end{bmatrix}$\n",
    "\n",
    "**<a href=\"https://baike.baidu.com/item/下三角矩阵\" target=\"_blank\">下三角矩阵</a>** ：主对角线以上都是零的**方阵**\n",
    "\n",
    "$\\begin{bmatrix}\n",
    "2&0&0&0 \\\\\n",
    "3&7&0&0 \\\\\n",
    "5&6&7&0 \\\\\n",
    "1&2&3&4\n",
    "\\end{bmatrix}$\n",
    "\n",
    "性质（行列式后面会说）\n",
    "1. 上（下）三角矩阵的行列式为对角线元素相乘\n",
    "2. 上（下）三角矩阵乘以系数后也是上（下）三角矩阵\n",
    "3. 上（下）三角矩阵间的加减法和乘法运算的结果仍是上（下）三角矩阵\n",
    "4. 上（下）三角矩阵的逆矩阵也仍然是上（下）三角矩阵"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[3 5 2 3]\n",
      " [7 2 9 6]\n",
      " [5 1 7 6]\n",
      " [1 2 8 4]]\n"
     ]
    }
   ],
   "source": [
    "# 创建一个5行4列矩阵\n",
    "A = np.random.randint(10,size=(4,4))\n",
    "\n",
    "print(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[3, 5, 2, 3],\n",
       "       [0, 2, 9, 6],\n",
       "       [0, 0, 7, 6],\n",
       "       [0, 0, 0, 4]])"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 上三角\n",
    "np.triu(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[3, 0, 0, 0],\n",
       "       [7, 2, 0, 0],\n",
       "       [5, 1, 7, 0],\n",
       "       [1, 2, 8, 4]])"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 下三角\n",
    "np.tril(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[3 0 0 0]\n",
      " [5 2 0 0]\n",
      " [2 9 7 0]\n",
      " [3 6 6 4]]\n",
      "-----\n",
      "[[3 7 5 1]\n",
      " [0 2 1 2]\n",
      " [0 0 7 8]\n",
      " [0 0 0 4]]\n"
     ]
    }
   ],
   "source": [
    "# 验证一下最后一个性质\n",
    "# 三角矩阵的逆矩阵也仍然是三角矩阵\n",
    "print(np.triu(A).T)\n",
    "print('-'*5)\n",
    "print(np.tril(A).T)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.3.4.对角矩阵\n",
    "\n",
    "**<a href=\"https://baike.baidu.com/item/对角矩阵\" target=\"_blank\">对角矩阵</a>** :主对角线之外的元素皆为0的**方阵** （单位矩阵属于对角矩阵中的一种）\n",
    "\n",
    "$\\begin{bmatrix}0&0&0 \\\\0&0&0 \\\\0&0&0\\end{bmatrix} \\begin{bmatrix}1&0&0 \\\\0&1&0 \\\\0&0&1\\end{bmatrix} \\begin{bmatrix}2&0&0 \\\\0&2&0 \\\\0&0&2\\end{bmatrix} \\begin{bmatrix}3&0&0 \\\\0&9&0 \\\\0&0&6\\end{bmatrix}$\n",
    "\n",
    "扩充：对角矩阵的运算包括和、差运算、数乘运算、同阶对角阵的乘积运算，且结果仍为对角阵\n",
    "\n",
    "而且有意思的是：**对角矩阵的矩阵幂运算等于其对应元素的幂运算**\n",
    "\n",
    "$\\begin{bmatrix}3&0&0 \\\\0&9&0 \\\\0&0&6\\end{bmatrix}^n = \\begin{bmatrix}3^n&0&0 \\\\0&9^n&0 \\\\0&0&6^n\\end{bmatrix}$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[3, 0, 0],\n",
       "       [0, 9, 0],\n",
       "       [0, 0, 6]])"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 简单创建\n",
    "np.diag([3,9,6])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[2, 0, 0],\n",
       "       [0, 2, 0],\n",
       "       [0, 0, 2]])"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.diag([2,2,2])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "################ 验证系列 ################"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[3 5 2 3]\n",
      " [7 2 9 6]\n",
      " [5 1 7 6]\n",
      " [1 2 8 4]]\n",
      "[[3 0 0 0]\n",
      " [0 2 0 0]\n",
      " [0 0 7 0]\n",
      " [0 0 0 4]]\n"
     ]
    }
   ],
   "source": [
    "# np.diag?\n",
    "print(A)\n",
    "\n",
    "# 获取对角元素，然后再生成对角矩阵\n",
    "B = np.diag(A.diagonal()) #或者 np.diag(np.diag(A))\n",
    "\n",
    "print(B)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 27,   0,   0,   0],\n",
       "       [  0,   8,   0,   0],\n",
       "       [  0,   0, 343,   0],\n",
       "       [  0,   0,   0,  64]])"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B.dot(B).dot(B)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 27,   0,   0,   0],\n",
       "       [  0,   8,   0,   0],\n",
       "       [  0,   0, 343,   0],\n",
       "       [  0,   0,   0,  64]])"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 对角矩阵的矩阵幂运算等于其对应元素的幂运算\n",
    "B**3"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.3.5.单位矩阵\n",
    "\n",
    "**<a href=\"https://baike.baidu.com/item/单位矩阵\" target=\"_blank\">单位矩阵</a>** ：单位矩阵是个**方阵**（行列相等），从左上角到右下角的对角线（称为主对角线）上的元素均为1。其他全都为0，eg:\n",
    "\n",
    "$\n",
    "\\begin{bmatrix}\n",
    "1&0&0 \\\\\n",
    "0&1&0 \\\\\n",
    "0&0&1\n",
    "\\end{bmatrix}\n",
    "$\n",
    "\n",
    "**任何`矩阵` x `单位矩阵` 都等于其`本身`** （反过来也一样（这个和1×a=a×1一个道理））"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 0.],\n",
       "       [0., 1.]])"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 定义一个2行的单位矩阵（列默认和行一致）\n",
    "# np.eye(rows,columns=rows)\n",
    "np.eye(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "################ 验证扩展 ################"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 0 0 0]\n",
      " [0 1 0 0]\n",
      " [0 0 1 0]\n",
      " [0 0 0 1]]\n"
     ]
    }
   ],
   "source": [
    "# 可以指定类型\n",
    "B = np.eye(4,dtype=int)\n",
    "\n",
    "print(B)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[3 5 2 3]\n",
      " [7 2 9 6]\n",
      " [5 1 7 6]\n",
      " [1 2 8 4]]\n"
     ]
    }
   ],
   "source": [
    "print(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[3, 5, 2, 3],\n",
       "       [7, 2, 9, 6],\n",
       "       [5, 1, 7, 6],\n",
       "       [1, 2, 8, 4]])"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 任何矩阵 x 单位矩阵 都等于其本身\n",
    "A.dot(B)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[3, 5, 2, 3],\n",
       "       [7, 2, 9, 6],\n",
       "       [5, 1, 7, 6],\n",
       "       [1, 2, 8, 4]])"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 反过来也一样（这个和1*a=a*1一个道理）\n",
    "B.dot(A)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.3.6.对称矩阵\n",
    "\n",
    "**<a href=\"https://baike.baidu.com/item/对称矩阵\" target=\"_blank\">对称矩阵</a>** :元素以主对角线为对称轴对应相等的**方阵**\n",
    "\n",
    "对称矩阵的转置是它本身：$A^T=A$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0 1 6 9]\n",
      " [1 2 4 7]\n",
      " [4 8 7 9]\n",
      " [3 6 8 0]]\n"
     ]
    }
   ],
   "source": [
    "A = np.random.randint(10,size=(4,4))\n",
    "\n",
    "print(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0 1 6 9]\n",
      " [1 2 4 7]\n",
      " [6 4 7 9]\n",
      " [9 7 9 0]]\n"
     ]
    }
   ],
   "source": [
    "B = np.triu(A)\n",
    "B += B.T - np.diag(A.diagonal())\n",
    "print(B)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ True,  True,  True,  True],\n",
       "       [ True,  True,  True,  True],\n",
       "       [ True,  True,  True,  True],\n",
       "       [ True,  True,  True,  True]])"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 验证一下\n",
    "B.T == B"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [],
   "source": [
    "################ 分步解释 ################"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0 1 6 9]\n",
      " [0 2 4 7]\n",
      " [0 0 7 9]\n",
      " [0 0 0 0]]\n"
     ]
    }
   ],
   "source": [
    "# 创建上三角矩阵\n",
    "B = np.triu(A)\n",
    "\n",
    "print(B)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 0  1  6  9]\n",
      " [ 1  4  4  7]\n",
      " [ 6  4 14  9]\n",
      " [ 9  7  9  0]]\n"
     ]
    }
   ],
   "source": [
    "# 上三角+它的逆矩阵（发现距离对角矩阵只是多加一次对角线上的元素）\n",
    "B += B.T\n",
    "\n",
    "print(B)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1, 6, 9],\n",
       "       [1, 2, 4, 7],\n",
       "       [6, 4, 7, 9],\n",
       "       [9, 7, 9, 0]])"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 所以减去对角线上的元素，得到对角矩阵\n",
    "B - np.diag(A.diagonal())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.4.逆矩阵\n",
    "\n",
    "**<a href=\"https://baike.baidu.com/item/逆矩阵\" target=\"_blank\">逆矩阵</a>** :设A是数域上的一个n阶方阵，若在相同数域上存在另一个n阶矩阵B，使得:`AB=BA=E` 则我们称B是A的逆矩阵(表示为$A^{-1}$)，而A则被称为可逆矩阵\n",
    "\n",
    "通俗话讲就是：**原矩阵×逆矩阵=逆矩阵×原矩阵=单位矩阵**\n",
    "\n",
    "### 2.4.1.消元法\n",
    "\n",
    "可能一看到逆矩阵，大家就想到**<a href=\"https://baike.baidu.com/item/代数余子式\" target=\"_blank\">代数余子式</a>** ，不过逆天要说的是，代数余子式就和我们程序员面试题一样，有些题目就是又繁琐实际运用又没多大意义的题目一样，很多时候面试官都不看面试题一眼，同样的那些出题老师自己解题一般都不会使用。我这边介绍一下方便简单的方法“**<a href=\"https://baike.baidu.com/item/消元法\" target=\"_blank\">消元法</a>**” \n",
    "\n",
    "比如求$\\begin{bmatrix}3&2 \\\\1&2\\end{bmatrix}^{-1}$，就可以表示为：\n",
    "\n",
    "$\\begin{bmatrix}3&2 \\\\1&2\\end{bmatrix}\\begin{bmatrix}x_{11}&x_{12} \\\\x_{21}&x_{22}\\end{bmatrix}=\\begin{bmatrix}1&0 \\\\0&1\\end{bmatrix}$\n",
    "\n",
    "转换成方程组：\n",
    "\n",
    "$\\begin{cases}\n",
    "\\begin{bmatrix}3&2 \\\\1&2\\end{bmatrix}\\begin{bmatrix}x_{11} \\\\x_{21}\\end{bmatrix}=\\begin{bmatrix}1 \\\\0\\end{bmatrix}\\\\\n",
    "\\begin{bmatrix}3&2 \\\\1&2\\end{bmatrix}\\begin{bmatrix}x_{12} \\\\x_{22}\\end{bmatrix}=\\begin{bmatrix}0 \\\\1\\end{bmatrix}\n",
    "\\end{cases} ==> 求方程组\\begin{cases}3x_{11}+2x_{21}=1\\\\1x_{11}+2x_{21}=0\\end{cases}和\\begin{cases}3x_{12}+2x_{22}=0\\\\1x_{12}+2x_{22}=1\\end{cases}的解$\n",
    "\n",
    "这样很轻松就能解出逆矩阵了\n",
    "\n",
    "$\\begin{cases}x_{11}=\\frac{1}{2}\\\\x_{21}=-\\frac{1}{4} \\end{cases}\\\\\\begin{cases}x_{12}=-\\frac{1}{2}\\\\x_{22}=\\frac{3}{4} \\end{cases}\\\\ ==> \\begin{bmatrix}\\frac{1}{2}&-\\frac{1}{2} \\\\-\\frac{1}{4}&\\frac{3}{4} \\end{bmatrix}$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[3 2]\n",
      " [1 2]]\n"
     ]
    }
   ],
   "source": [
    "A = np.array([[3,2],[1,2]])\n",
    "\n",
    "print(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.5 , -0.5 ],\n",
       "       [-0.25,  0.75]])"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 求A的逆矩阵\n",
    "np.linalg.inv(A)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.4.2.二阶方阵公式\n",
    "\n",
    "如果只是2阶方阵，有更简单的公式（**只能2阶使用，而消元法不受限制**）矩阵是否可逆就看分母是否为0\n",
    "\n",
    "$\\large{\\begin{bmatrix}a_{11}&a_{12} \\\\a_{21}&a_{22}\\end{bmatrix}=\\frac{1}{a_{11}a_{22}-a_{12}a_{21}}\\begin{bmatrix}a_{22}&-a_{12} \\\\-a_{21}&a_{11}\\end{bmatrix}}$\n",
    "\n",
    "比如求$\\begin{bmatrix}3&2 \\\\1&2\\end{bmatrix}^{-1}$：\n",
    "\n",
    "$\\frac{1}{3×2-2×1}\\begin{bmatrix}2&-2 \\\\-1&3\\end{bmatrix}=\\begin{bmatrix}\\frac{1}{2}&-\\frac{1}{2} \\\\-\\frac{1}{4}&\\frac{3}{4} \\end{bmatrix}$\n",
    "\n",
    "### 扩展系列：伪逆矩阵\n",
    "\n",
    "非方阵可以求 **<a href=\"https://baike.baidu.com/item/伪逆矩阵\" target=\"_blank\">伪逆矩阵</a>** `AXA=A,XAX=X`\n",
    "\n",
    "判断矩阵是否可逆:\n",
    "\n",
    "$$det\\begin{bmatrix}a_{11}&a_{12} \\\\a_{21}&a_{22}\\end{bmatrix}=a_{11}a_{12}-a_{12}a_{21}\\\\det\\begin{bmatrix}a_{11}&a_{12}&a_{13} \\\\a_{21}&a_{22}&a_{23}\\\\a_{31}&a_{32}&a_{33}\\end{bmatrix}=a_{11}a_{22}a_{33}+a_{12}a_{23}a_{31}+a_{13}a_{21}a_{32}-a_{13}a_{22}a_{31}-a_{12}a_{21}a_{33}-a_{11}a_{23}a_{32}$$\n",
    "\n",
    "方法很多(比如还可以通过余子式)，公式其实有规律，你可以先摸索下(给个提示)：\n",
    "\n",
    "|项|正负|\n",
    "|---|---|\n",
    "|a11a22|+|\n",
    "|a12a21|-|\n",
    "\n",
    "|项|正负|\n",
    "|---|---|\n",
    "|a11a22a33|+|\n",
    "|a11a23a32|-|\n",
    "|a12a21a33|-|\n",
    "|a12a23a31|+|\n",
    "|a13a21a32|+|\n",
    "|a13a22a31|-|\n",
    "\n",
    "\n",
    "程序比较简单：`np.linalg.det(A)`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[7 3 6]\n",
      " [5 3 1]]\n"
     ]
    }
   ],
   "source": [
    "A = np.array([[7, 3, 6],[5, 3, 1]])\n",
    "\n",
    "print(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "ename": "LinAlgError",
     "evalue": "Last 2 dimensions of the array must be square",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mLinAlgError\u001b[0m                               Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-47-2ce8e7bdf499>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;31m# 不等于0就是可逆\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlinalg\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdet\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mA\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m~/anaconda3/lib/python3.6/site-packages/numpy/linalg/linalg.py\u001b[0m in \u001b[0;36mdet\u001b[0;34m(a)\u001b[0m\n\u001b[1;32m   1869\u001b[0m     \u001b[0ma\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0masarray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1870\u001b[0m     \u001b[0m_assertRankAtLeast2\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1871\u001b[0;31m     \u001b[0m_assertNdSquareness\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1872\u001b[0m     \u001b[0mt\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mresult_t\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_commonType\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1873\u001b[0m     \u001b[0msignature\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'D->D'\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misComplexType\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32melse\u001b[0m \u001b[0;34m'd->d'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/anaconda3/lib/python3.6/site-packages/numpy/linalg/linalg.py\u001b[0m in \u001b[0;36m_assertNdSquareness\u001b[0;34m(*arrays)\u001b[0m\n\u001b[1;32m    209\u001b[0m     \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0marrays\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    210\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mmax\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m!=\u001b[0m \u001b[0mmin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 211\u001b[0;31m             \u001b[0;32mraise\u001b[0m \u001b[0mLinAlgError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Last 2 dimensions of the array must be square'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    212\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    213\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_assertFinite\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0marrays\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mLinAlgError\u001b[0m: Last 2 dimensions of the array must be square"
     ]
    }
   ],
   "source": [
    "# 不等于0就是可逆\n",
    "np.linalg.det(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "ename": "LinAlgError",
     "evalue": "Last 2 dimensions of the array must be square",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mLinAlgError\u001b[0m                               Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-48-0af3c81a492f>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;31m# 必须是方阵的验证\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlinalg\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minv\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mA\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m~/anaconda3/lib/python3.6/site-packages/numpy/linalg/linalg.py\u001b[0m in \u001b[0;36minv\u001b[0;34m(a)\u001b[0m\n\u001b[1;32m    521\u001b[0m     \u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mwrap\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_makearray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    522\u001b[0m     \u001b[0m_assertRankAtLeast2\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 523\u001b[0;31m     \u001b[0m_assertNdSquareness\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    524\u001b[0m     \u001b[0mt\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mresult_t\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_commonType\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    525\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/anaconda3/lib/python3.6/site-packages/numpy/linalg/linalg.py\u001b[0m in \u001b[0;36m_assertNdSquareness\u001b[0;34m(*arrays)\u001b[0m\n\u001b[1;32m    209\u001b[0m     \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0marrays\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    210\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mmax\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m!=\u001b[0m \u001b[0mmin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 211\u001b[0;31m             \u001b[0;32mraise\u001b[0m \u001b[0mLinAlgError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Last 2 dimensions of the array must be square'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    212\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    213\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_assertFinite\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0marrays\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mLinAlgError\u001b[0m: Last 2 dimensions of the array must be square"
     ]
    }
   ],
   "source": [
    "# 必须是方阵的验证\n",
    "np.linalg.inv(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[-0.00632911  0.15189873]\n",
      " [-0.05696203  0.16708861]\n",
      " [ 0.20253165 -0.26075949]]\n"
     ]
    }
   ],
   "source": [
    "# 有时候还是需要求逆矩阵\n",
    "# 那就可以求它的伪逆矩阵\n",
    "X = np.linalg.pinv(A)\n",
    "\n",
    "print(X)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[7., 3., 6.],\n",
       "       [5., 3., 1.]])"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# A*X*A=A\n",
    "A.dot(X).dot(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.00632911,  0.15189873],\n",
       "       [-0.05696203,  0.16708861],\n",
       "       [ 0.20253165, -0.26075949]])"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# X*A*X=X\n",
    "X.dot(A).dot(X)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [],
   "source": [
    "################ 简单说下mat ################"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[3 2]\n",
      " [1 2]]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "numpy.matrixlib.defmatrix.matrix"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 创建一个矩阵\n",
    "A = np.mat([[3,2],[1,2]])\n",
    "\n",
    "print(A)\n",
    "type(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[ 0.5 , -0.5 ],\n",
       "        [-0.25,  0.75]])"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 求它的逆矩阵\n",
    "A.I"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[3, 1],\n",
       "        [2, 2]])"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# A^T\n",
    "A.T"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[11, 10],\n",
       "        [ 5,  6]])"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# *默认就是矩阵乘法\n",
    "A * A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# 更多自己查看下帮助文档把，用法和array基本上一样，\n",
    "# 我这边只是简单提一下，怕你们不去看（所有和矩阵相关的东西，里面都有封装，很方便）\n",
    "np.mat?"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
